﻿/*****************************************
 * 
 *  copyright (c) by ylshen
 * 
 *  author : ylshen (syl.lucky@gmail.com)
 * 
 **************************************** */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using JYStockAnalyser.Model;
using JYStockAnalyser.DA;

namespace JYStockAnalyser.Face
{
    /// <summary>
    /// 股票及指标操作外观
    /// </summary>
    public class StockManageFace : System.MarshalByRefObject
    {
        /// <summary>
        /// 获取主界面显示的消息
        /// </summary>
        /// <returns></returns>
        public string GetMainShowMessage()
        {
            return "本软件提供的数据均为上市公司及证券交易所法定定期发布的官方数据，市场有风险，投资需谨慎";
        }

        /// <summary>
        /// 获取可统计的最小和最大的年份
        /// </summary>
        /// <returns></returns>
        public YearQuarter[] GetMinAndQuarter()
        {
            return new YearQuarter[] { new YearQuarter(1992, 4), new YearQuarter(2008, 1) };
        }

        public int[][] GetDefaultSingleStockAnalyseGuideLines()
        {
            int[][] result = new int[3][];
            result[0] = new int[] { 10003, 10007, 10018, 10012, 10009 };
            result[1] = new int[] { 83, 2006, 46 };
            result[2] = new int[] { 3002, 3055, 83 };
            return result;
        }

        public int[][] GetDefaultFinancialAnalyseGuideLines()
        {
            int[][] result = new int[3][];
            result[0] = new int[] { 4001, 4002, 4003, 4004, 4005 };
            result[1] = new int[] { 5001, 5002, 5003 };
            result[2] = new int[] { 6001, 6002, 6003 };
            return result;
        }


        public List<string> GetAllStockNOAndNames()
        {
            StockMapper stockMapper = new StockMapper();
            return stockMapper.FindAllStockNOAndNames();
        }

        public List<Stock> FindAllStocks()
        {
            StockMapper stockMapper = new StockMapper();
            return stockMapper.FindAllStocks();
        }

        /// <summary>
        /// 获取所有的财务报表（名称）
        /// </summary>
        /// <returns></returns>
        public List<string> GetAllReports()
        {
            return new List<string> { "主要财务指标", "资产负债表", "利润分配表", "现金流量表" };
        }

        /// <summary>
        /// 获取所有财务评估指标分类
        /// </summary>
        /// <returns></returns>
        public List<string> GetAllFinancialGuideLineCategories()
        {
            return new List<string> { "成长性", "经营能力", "盈利能力", "偿债能力", "现金流量", "财务速览" };
        }

        /// <summary>
        /// 获取指标股票在指定季度、指定报表里面的指标值（若无值，则创建未声明值）
        /// </summary>
        /// <param name="stock"></param>
        /// <param name="quarter"></param>
        /// <param name="report"></param>
        /// <returns></returns>
        public object[] SearchGuideLines(string stock, YearQuarter quarter, string report)
        {
            StockMapper stockMapper = new StockMapper();
            GuideLineMapper mapper = new GuideLineMapper();
            return new object[] { stockMapper.FindStockByNO(stock), mapper.FindGuideLines(stock, quarter, report) };
        }

        /// <summary>
        /// 获取所有的股票种类
        /// </summary>
        /// <returns></returns>
        public List<int> GetAllStockKinds()
        {
            //1 金融　2　非金融
            return new List<int> { 1, 2 };
        }

        /// <summary>
        /// 获取所有的指标类型
        /// 按财报->股票类型　两级分类
        /// </summary>
        public Dictionary<string, Dictionary<int, List<GuideLineType>>> FindAllGuideLineTypes()
        {
            List<string> reports = GetAllReports();
            List<int> stockKinds = GetAllStockKinds();

            Dictionary<string, Dictionary<int, List<GuideLineType>>> result = new Dictionary<string,Dictionary<int,List<GuideLineType>>>();

            GuideLineMapper mapper = new GuideLineMapper();
            foreach (string report in reports)
            {
                result.Add(report, new Dictionary<int, List<GuideLineType>>());
                foreach (int stockKind in stockKinds)
                {                    
                    result[report].Add(stockKind, mapper.FindTypes(report, stockKind));                    
                }
            }
            return result;
        }

        /// <summary>
        /// 获取所有的财务指标类型
        /// 按财报->股票类型　两级分类
        /// </summary>
        /// <returns></returns>
        public Dictionary<string, Dictionary<int, List<GuideLineType>>> FindAllFinancialGuideLineTypes()
        {
            List<string> reports = GetAllFinancialGuideLineCategories();
            List<int> stockKinds = GetAllStockKinds();

            Dictionary<string, Dictionary<int, List<GuideLineType>>> result = new Dictionary<string, Dictionary<int, List<GuideLineType>>>();

            GuideLineMapper mapper = new GuideLineMapper();
            foreach (string report in reports)
            {
                result.Add(report, new Dictionary<int, List<GuideLineType>>());
                foreach (int stockKind in stockKinds)
                {
                    result[report].Add(stockKind, mapper.FindTypes(report, stockKind));
                }
            }
            return result;
        }

        public List<string> GetAllTrades()
        {
            StockMapper stockMapper = new StockMapper();
            return stockMapper.FindAllTrades();
        }

        public object[] SearchGuideLines(string stockNO, string analyseTimeType, YearQuarter beginQuarter, YearQuarter endQuarter, GuideLineType type)
        {
            StockMapper stockMapper = new StockMapper();
            GuideLineMapper guideLineMapper = new GuideLineMapper();

            Stock stock = stockMapper.FindStockByNO(stockNO);

            List<GuideLine> lines = guideLineMapper.FindGuideLines(stockNO, analyseTimeType, beginQuarter, endQuarter, type);

            return new object[] { stock, lines };
        }

        public object[] SearchGuideLines(string stockNO, YearQuarter yearQuarter, GuideLineType[] guideLineTypes)
        {
            StockMapper stockMapper = new StockMapper();
            GuideLineMapper guideLineMapper = new GuideLineMapper();

            Stock stock = stockMapper.FindStockByNO(stockNO);

            List<GuideLine> lines = guideLineMapper.FindGuideLines(stockNO, yearQuarter, guideLineTypes);

            return new object[] { stock, lines };
        }

        public object[] SearchGuideLines(string stockNO, string analyseTimeType, YearQuarter beginQuarter, YearQuarter endQuarter, GuideLineType[] guideLineTypes)
        {
            object[] objs = new object[guideLineTypes.Length + 2];
            StockMapper stockMapper = new StockMapper();
            GuideLineMapper guideLineMapper = new GuideLineMapper();

            Stock stock = stockMapper.FindStockByNO(stockNO);
            objs[0] = stock;

            if (stock == null)
                return objs;
          

            for (int i = 0; i < guideLineTypes.Length; i++)
            {
                objs[i + 2] = guideLineMapper.FindGuideLines(stockNO, analyseTimeType, beginQuarter, endQuarter, guideLineTypes[i]);
            }

           
            if (analyseTimeType.Equals("年"))
            {
                if (endQuarter.Year.Equals(GetMinAndQuarter()[1].Year))
                {
                    endQuarter.Quarter = GetMinAndQuarter()[1].Quarter;
                }
                else
                {
                    endQuarter.Quarter = 4;
                }
            }

            objs[1] = GetEstimateValue(stockNO, endQuarter);   

            
       
            return objs;
        }

        public object[] SearchGuideLines(string[] stockNOs, string analyseTimeType, YearQuarter beginQuarter, YearQuarter endQuarter, GuideLineType guideLineType)
        {
            object[] objs = new object[stockNOs.Length];
            StockMapper stockMapper = new StockMapper();
            GuideLineMapper guideLineMapper = new GuideLineMapper();

            for (int i = 0; i < stockNOs.Length; i++)
            {
                objs[i] = guideLineMapper.FindGuideLines(stockNOs[i], analyseTimeType, beginQuarter, endQuarter, guideLineType);
            }

            return objs;
        }

        /// <summary>
        /// 获取估值结果
        /// </summary>
        /// <param name="stockNO"></param>
        /// <param name="quarter"></param>
        /// <returns></returns>
        public decimal[] GetEstimateValue(string stockNO, YearQuarter quarter)
        {
            GuideLineMapper mapper = new GuideLineMapper();
            return mapper.GetEstimateValue(stockNO, quarter);
        }

        /// <summary>
        /// 估值
        /// </summary>
        /// <param name="stockNO"></param>
        /// <param name="quarter"></param>
        /// <returns></returns>
        public decimal[] EstimateValues(string stockNO, YearQuarter quarter)
        {
            EstimateRule theRule;         
            decimal standardResult = EstimateValue(stockNO, quarter, out theRule);

            decimal v1 = decimal.Round(standardResult * theRule.ASafetyCoefficient, 2);
            decimal v2 = decimal.Round(standardResult * theRule.BSafetyCoefficient, 2);
            decimal v3 = decimal.Round(standardResult * theRule.CSafetyCoefficient, 2);
            decimal v4 = decimal.Round(standardResult * theRule.DSafetyCoefficient, 2);
            decimal v5 = decimal.Round(standardResult * theRule.ESafetyCoefficient, 2);

            return new decimal[] { v1, v2, v3, v4, v5 };
        }

        private static decimal EstimateValue(string stockNO, YearQuarter quarter, out EstimateRule theRule)
        {
            decimal standardResult;
            theRule = m_getEstimateRule(quarter);
            if (theRule == null)
            {
                throw new Exception("没有找到估值算法!");
            }

            //获取股票详细信息
            StockMapper stockMapper = new StockMapper();
            Stock stock = stockMapper.FindStockByNO(stockNO);

            //获取股票行业系数
            decimal tradeValue = theRule.TradeCoefficients[stock.Trade];

            GuideLineMapper guideLineMapper = new GuideLineMapper();

            //获取指标值
            List<GuideLine> lines = guideLineMapper.FindGuideLines(stockNO, quarter, theRule.GuideLineTypes.ToArray());

            
            standardResult = 0m;

            foreach (GuideLine line in lines)
            {
                if (!line.Value.Equals(GuideLine.UNDEFINED_VALUE))
                {
                    standardResult += line.Value;
                }
            }

            foreach (KeyValuePair<string, decimal> commonValue in theRule.CommonCoefficients)
            {
                standardResult *= commonValue.Value;
            }

            standardResult *= tradeValue;

            return standardResult;
        }

        private static EstimateRule m_getEstimateRule(YearQuarter quarter)
        {
            EstimateRule theRule;
            theRule = null;

            //从非默认规则中找寻有效规则
            foreach (EstimateRule rule in ServerCache.Instance.EstimateRules)
            {
                if (quarter.CompareTo(rule.BeginYearQuarter) >= 0 && quarter.CompareTo(rule.EndYearQuarter) <= 0)
                {
                    theRule = rule;
                    break;
                }
            }
            //若没有在非默认规则中找到相应规则，则指定为默认规则
            if (theRule == null)
            {
                theRule = ServerCache.Instance.DefaultEstimateRule;
            }

            return theRule;
        }

        private decimal[] GetUnDefinedEstimateResult()
        {
            return new decimal[] { GuideLine.UNDEFINED_VALUE, GuideLine.UNDEFINED_VALUE, GuideLine.UNDEFINED_VALUE, GuideLine.UNDEFINED_VALUE, GuideLine.UNDEFINED_VALUE };
        }

        public byte InsertORUpdateGuideLine(string[] stockNO, GuideLine[] line)
        {
            GuideLineMapper mapper = new GuideLineMapper();
            try
            {
                for (int i = 0; i < stockNO.Length; i++)
                {
                    mapper.InsertORUpdateGuideLine(stockNO[i], line[i]);
                }
                return 1;
            }
            catch (ORException)
            {
                return 110;
            }
        }

        public List<SecurityOrderItem> GetOrderedSecurityOrderItems(string orderType, int pageIndex, int pageSize, out int pageCount)
        {
            pageCount = 0;
            OtherDA da = new OtherDA();
            YearQuarter quarter = GetMinAndQuarter()[1];

            List<SecurityOrderItem> items = da.GetAllSecurityItems(quarter);

            if (orderType.Equals("上涨空间"))
            {
                items.Sort(new Comparison<SecurityOrderItem>(
                    delegate(SecurityOrderItem item1, SecurityOrderItem item2)
                    {
                        return -item1.Growth.CompareTo(item2.Growth);
                    }));
            }
            else 
            {
                items.Sort(new Comparison<SecurityOrderItem>(
                    delegate(SecurityOrderItem item1, SecurityOrderItem item2)
                    {
                        return item1.StockNO.CompareTo(item2.StockNO);
                    }));
            }

            for (int i = 0; i < items.Count; i++)
            {
                items[i].Order = i + 1;
            }

            pageCount = (int)(items.Count / pageSize) + 1;

            int startIndex = (pageIndex - 1) * pageSize;
            pageSize = items.Count < (pageSize + startIndex) ? items.Count - startIndex : pageSize;
            return new List<SecurityOrderItem>(items.GetRange(startIndex, pageSize));
        }

        /// <summary>
        /// 获取利润增速表
        /// </summary>
        /// <returns></returns>
        public List<GrowthSpeedOrderItem> GetOrderedGrowthSpeedOrderItems(string periodType, string orderType, YearQuarter beginQuarter, YearQuarter endQuarter, int pageIndex, int pageSize, out int pageCount)
        {
            int period = 0;
            pageCount = 0;
            if (periodType.Equals("年"))
            {
                beginQuarter.Quarter = 4;
                endQuarter.Quarter = 4;
                period = endQuarter.Year - beginQuarter.Year;
            }
            else if (periodType.Equals("季度"))
            {
                period = (endQuarter.Year - beginQuarter.Year) * 4 + endQuarter.Quarter - beginQuarter.Quarter;
            }

            YearQuarter[] minMaxQuarter = GetMinAndQuarter();

            if (endQuarter.Year.Equals(minMaxQuarter[1].Year) && endQuarter.Quarter > minMaxQuarter[1].Quarter)
            { endQuarter.Quarter = minMaxQuarter[1].Quarter; }

            OtherDA da = new OtherDA();
            List<GrowthSpeedOrderItem> items = da.GetAllOrderItems(periodType, period, beginQuarter, endQuarter);

            if (orderType.Equals("净利润复合增长率"))
            {             
                items.Sort(new Comparison<GrowthSpeedOrderItem>(
                    delegate(GrowthSpeedOrderItem item1, GrowthSpeedOrderItem item2)
                    {
                        return -item1.GrowhCompoundRate.CompareTo(item2.GrowhCompoundRate);
                    }));
            }
            else
            {
                items.Sort(new Comparison<GrowthSpeedOrderItem>(
                                   delegate(GrowthSpeedOrderItem item1, GrowthSpeedOrderItem item2)
                                   {
                                       return item1.StockNO.CompareTo(item2.StockNO);
                                   }));
            }

            for(int i = 0; i < items.Count; i++)
            {
                items[i].Order = i + 1;
            }

            pageCount = (int)(items.Count / pageSize) + 1;

            int startIndex = (pageIndex - 1) * pageSize;
            pageSize = items.Count < (pageSize + startIndex) ? items.Count - startIndex : pageSize;
            return new List<GrowthSpeedOrderItem>(items.GetRange(startIndex, pageSize));
        }

        /// <summary>
        /// 对所有股票在指定季度进行估值并存储估值结果
        /// </summary>
        /// <param name="beginQuarter"></param>
        /// <param name="endQuarter"></param>
        public byte EstimateAndSave(YearQuarter quarter)
        {
            List<Stock> stocks = FindAllStocks();
            GuideLineMapper mapper = new GuideLineMapper();
          
            foreach (Stock stock in stocks)
            {
                decimal[] values = EstimateValues(stock.NO, quarter);

                try
                {
                    mapper.InsertORUpdateEstimateValues(stock.NO, quarter, values[0], values[1], values[2], values[3], values[4]);
                }
                catch (Exception)
                {
                    return 110;
                }
             }
            return 1;
        }
    }
}
